استفاده از توابع پارامتریک در طراحی گزارشات چاپی تدبیر

تذکر: به لحاظ نیاز به آشنایی با SQL، نحوۀ طراحی گزارشات چاپی تدبیر و همینطور آشنایی با مفاهیم تحلیل و طراحی پایگاه داده‌ها، بحث این نوشته؛ زیرساختی و مخاطب آن -بیشتر- مدیران فنی سیستم مالی تدبیر و نمایندگان و کارکنان بخشهای استقرار و پشتیبانی شرکت پردازش موازی سامان هستند. کاربری عادی نرم‌افزارهای تدبیر نیازی به یادگیری این مفاهیم ندارد.

یکی از خواسته‌های همیشگی کاربران نرم‌افزارهای مبتنی بر پایگاه داده‌ها، امکان نمایش انواع مختلف فیلدهای اطلاعاتی در گزارشات چاپیِ فرمهای عملیاتی یا گزارشی است. برخی از این فیلدها مرتبط با موضوع گزارش چاپی هستند (مثل انواع اطلاعات مربوط به «فاکتور فروش» در گزارش چاپی فاکتور فروش) و انتظار می‌رود نرم‌افزار، امکان نمایش این دسته از اطلاعات را در گزارش چاپی بدون هیچ‌گونه محدودیتی فراهم کند. اما، بعضاً، درخواستها دربردارندۀ امکان نمایش فیلدهای اطلاعاتی به دست آمده از محاسبات پیچیده و یا مربوط به فیلدهای اطلاعاتی نامرتبط یا با ارتباط دور با موضوع اصلی گزارش است (مثلاً امکان نمایش جمع کل چکهای برگشتی دریافتی از مشتری در فاکتور فروش صادر شده برای او).

یکی از نقاط قوت نرم‌افزار مالی و اداری تدبیر، گزارش‌ساز قدرتمند آن است که با اتکا به مجموعۀ وسیعی از توابع از پیش آماده و ایندکسهای چاپی؛ امکان پاسخگویی بسیاری از درخواستهای کاربران در این زمینه را بدون نیاز به اعمال تغییر در کد اصلی برنامه و انتظار جهت انتشار بستۀ نهایی فراهم می‌آورد. با این وجود، نظر به وسعت پایگاه داده‌های سیستم، همواره پاسخگویی به برخی از درخواستها نیازمند اضافه شدن توابع یا اندیسهای چاپی جدید در کد برنامه بوده و با توجه به زمان مورد نیاز جهت کنترل کیفیت و رفع اشکالات احتمالی تا رسیدن به نقطۀ پایداری، کاربر باید در این موارد خاص انتظار چندماهه‌ای را تا دریافت بستۀ جدید نرم‌افزار تحمل کند.

ارائۀ طرحی برای حل این مشکل و کاهش زمان انتظار کاربران، یکی از اهداف اصلی تعیین شده برای آخرین نسخۀ نرم‌افزار مالی تدبیر بود که هم‌اکنون در نسخۀ 7.69 در قالب قابلیتهای «امکان استفاده از توابع پارامتریک در گزارشات چاپی» و همینطور «امکان توسعۀ موجودیتهای پارامتریک» انجام شده و در دسترس قرار گرفته است. در این مطلب، با ارائۀ چند مثال کاربردی نحوۀ استفاده از این قابلیتها را برای پاسخگویی به نیازهای کاربران در گزارشات چاپی شرح می‌دهیم.

برای شروع کار تلاش می‌کنیم مسئلۀ ساده‌ای را که قبلاً با استفاده از راه حلهای قدیمی‌تر حل شده با استفاده از توابع پارامتریک حل کنیم. «فاکتور خرید» را در نظر بگیرید، فرض کنیم می‌خواهیم در این فاکتور «نام مشتری فاکتور» را با استفاده از راهکار جدید نمایش دهیم.

طبق روال طراحی گزارشات چاپی، روی فرم فاکتور خرید با فشردن کلید ترکیبی Alt+Q (پیش‌نمایش چاپ) از پنجرۀ «مدیریت گزارشات» یکی از گزارشات چاپی آمادۀ فاکتور خرید را انتخاب کرده، با فشردن دکمۀ «تغییر فرم» گزارش‌‎ساز را باز می‌کنیم و با فشردن کلید ترکیبی Alt+Z آن را به نام دیگری ذخیره می‌کنیم و در گزارش جدید روی برچسب اطلاعاتی روبروی «فروشنده» کلیک راست می‌کنیم. در گزارش چاپی فعلی، نام فروشنده از طریق یک اندیس چاپی نمایش داده می‌شود و ما می‌خواهیم به جای این کار از توابع پارامتریک استفاده کنیم. از منوی کلیک راست پنجرۀ ویژگیهای فیلد، عنوان «تابع پارامتریک» را انتخاب می‌کنید یا با فشردن کلید ترکیبی Alt+P در این پنجره، فرمان متناظر را اجرا کنید. با اجرای فرمان یاد شده، پنجرۀ تعریف تابع پارامتریک باز می‌شود، از کمبوی «سیستم» عنوان «خرید و فروش»، از کمبوی «نوع» عنوان «موجودیتهای عملیاتی» و از لیست موجودیتها «فاکتور خرید» را انتخاب و باز کنید.

همچنان که در تصویر بالا مشاهده می‌کنید، در لیست موجودیتها، فیلدهای اطلاعاتی فاکتور خرید به همراه ارتباطات آنها و همینطور موجودیتهای وابسته (ریز اقلام فاکتور خرید و ...) نمایش داده شده می‌شود. فیلد «مشتری» را باز کنید و «نام» را انتخاب کنید. در کادر متنی بالای کمبوی «سیستم» عنوان کامل فیلد انتخابی (نام مشتری فاکتور خرید) نمایش داده می‌شود.

تا اینجای کار، فیلد خروجی مورد نظرمان را مشخص کرده‌ایم. در ادامه باید مشخص کنیم که دقیقاً تمایل داریم نام مشتریِ کدام فاکتور خرید نمایش داده شود (شرط تابع را مشخص کنیم). شرط تابع برای این مسأله، یک «فیلد کلیدی» مربوط به فاکتور خرید است، فیلد کلیدی فاکتور خرید می‌تواند «شماره»ی آن باشد که از طریق اندیس چاپی شمارۀ 0 در دسترس قرار دارد (شمارۀ این اندیس با کلیک راست بر روی فیلد اطلاعاتی روبروی برچسب «شماره» و از طریق پنجرۀ «ویژگیها» در دسترس قرار می‌گیرد). برای تعیین این شرط روی دکمۀ «تعیین شرط اول» در کادر «شرط اول» کلیک می‌کنیم و در پنجرۀ باز شده مشخصه مورد نظر را «شماره» و مقدار آن را برابر پارامتر با اندیس 0 قرار می‌دهیم.

با تأیید شرط، عبارت متناظر آن در کادر شرط اول نمایش داده شده و با فشردن دکمۀ «پیش‌نمایش» در کادر «پیش‌نمایش خروجی»، سیستم، پارامترهای گزارش چاپی (در اینجا «شمارۀ فاکتور») را سؤال کرده و نام مشتری متناظر را نمایش می‌دهد. تأیید تابع طراحی شده باعث درج آن در گزارش چاپی می‌شود و با ذخیرۀ گزارش امکان اجرا و مشاهدۀ نتایج آن روی فاکتورهای خرید را خواهید داشت.

همانطور که با اجرای مثال بالا متوجه شده‌اید برای انواع مختلف توابع پارامتریک چاپی؛ دو نوع شرط در دو سطح متفاوت می‌توان تعیین کرد (شرطهای هر سطح می‌تواند به نوبۀ خود ترکیبی از عملگرهای منطقی AND و OR و شامل شرطهای پیچیده باشند). علت وجود دو سطح برای تعیین شرطها آن است که اندیسهای چاپی قابل استفاده در شرطها عملاً در دو سطح (Master/Slave یا رکورد اصلی و رکورد ریزاقلام یا رکورد پدر و فرزند) در دسترس است. اندیسهای چاپی مربوط به رکورد پدر (مثلاً فاکتور خرید) در گزارش‌ساز تدبیر از طریق تابع استاندارد GetParametersAt و اندیسهای چاپی مربوط به رکورد فرزند (مثلاً ریزاقلام فاکتور خرید) از طریق تابع استاندارد ColumnValue در دسترس قرار دارد و اغلب لازم است شرطهای درگیر با رکورد پدر در سطح اول (با شرطهای مقداری مشخص شده با «پارامتر») و شرطهای درگیر با رکوردهای فرزند در سطح دوم (با شرطهای مقداری مشخص شده با «مقدار سطر») تعیین شوند. در مثال بالا چون، صورت مسئلۀ ما (نمایش نام فروشنده) ربطی به ریزاقلام فاکتور خرید نداشت نیازی به گذاشتن شرط در سطح دوم نداشتیم. در مثال بعدی که مثال پیچیده‌تری است نیاز داریم از شرط سطح دوم هم استفاده کنیم

نکتۀ دیگری که از مثال بالا می‌توان به آن پی برد آن است که ساختار توابع پارامتریک چاپی وابسته به «موجودیتهای گزارشات پارامتریک» است. «گزارشات پارامتریک» که از طریق منوی «امکانات» سیستم مالی در دسترس قرار می‌گیرد اطلاعات موجودیتهای تدبیر را به زبان کاربر در اختیار می‌گذارد و می‌توان با ترکیب فیلدهای اطلاعاتی و اضافه کردن شرطهای جدید با استفاده از آن گزارشات جدیدی را به سیستم اضافه کرد. در مثال بالا، فیلد مورد نظر ما یک فیلد ساده و آماده و دم دست از موجودیت «فاکتور خرید» بود (نام مشتری). اما اگر فیلد مورد نظر ما به صورت آماده در اطلاعات موجودیتهای گزارشات وجود نداشته باشد و باید از طریق محاسبات دیگر به دست بیاید باید چه کار کنیم؟ مثال بعدی روش حل مسائلی با این درجه از پیچیدگی را هم به ما یاد می‌دهد.

صورت مسئلۀ مثال بعدی ما این است:

می‌خواهیم در چاپ فاکتور فروش، به ازای هر سطر اقلام کالا، مبلغ اضافات فاکتور فروش، بر اساس نسبتِ مبلغ کل سطر؛ به جمع کل مبلغ همۀ سطرها تسهیم شده، به عنوان «اضافات سطر» نمایش داده شود.

فرضاً اگر اضافات کل فاکتور فروش ما 10000 ریال است و در سطر اول از کالای شماره 1 با قیمت واحد 10000 ریال 10 عدد و در سطر دوم از کالای شماره 2 با قیمت واحد 25000 ریال 6 عدد داریم (جمع مبلغ کالاها: 10000*10+25000*6 = 250000) اضافات سطر کالای شماره 1 برابر نسبت (250000)/(10*10000)=0.4 ضرب در اضافات کل (10000) و برابر با 4000 ریال و با همین محاسبه اضافات سطر کالای شماره 2 برابر 6000 ریال خواهد بود. تصویر زیر گزارش چاپی پیش‌فرض را برای مثال یاد شده نمایش می‌دهد.

همچنان که از صورت مسئله مشخص است پیش‌نیاز نمایش چنین اطلاعاتی در گزارش چاپی آن است که بتوانیم «سهم اضافات هر سطر» را با توجه به سناریوی تسهیم تعیین شده محاسبه کنیم. برای این کار ابتدا از طریق منوی «امکانات»، فرمان «گزارشات پارامتریک» را اجرا کرده، با استفاده از کلید ترکیبی Alt+E پنجرۀ «موجودیتهای تعریف شده» را باز می‌کنیم. از کمبوی «سیستم» عنوان «خرید و فروش» و از کمبوی «نوع» عنوان «عملیات» را انتخاب می‌کنیم. از فهرست موجودیتهای قابل انتخاب روی «فاکتور فروش» دو بار کلیک می‌کنیم تا فهرست موجودیتهای وابسته به آن را مشاهده کنیم.

ردیف «ریز اقلام فاکتور فروش» را انتخاب و سپس کلیک راست کرده و فرمان «ایجاد کپی از موجودیت ردیف جاری» را اجرا می‌کنیم (علت این کار آن است که سیستم اجازۀ تغییر موجودیتهای سیستمی -یعنی آن دسته از موجودیتها که در ستون «ردیف» آنها نماد «قفل» نمایش داده می‌شود- را نمی‌دهد و ما برای حل مسئلۀ خودمان نیاز داریم فیلد محاسباتی اضافات سطر را به موجودیت «ریز اقلام فاکتور فروش» اضافه کنیم، با ایجاد کپی -چون کپی یک موجودیت سیستمی یک موجودیت کاربری است- سیستم اجازۀ اصلاح آن را می‌دهد و می‌توانیم از آن استفاده کنیم).

فرمان ایجاد کپی، موجودیت «کپی ریز اقلام فاکتور فروش» را با نما (VIEW در SQL)ی کپی شده‌اش (با نام پیش‌فرض UD___TPRSalesFactorArticleView__ ) می‌سازد. ما برای اضافه کردن فیلد محاسباتی مورد نظرمان از طریق Microsoft SQL Server Management Studio به سراغ دیتابیس شرکت رفته و VIEWی مورد نظر را پیدا کرده آن را برای ویرایش باز می‌کنیم.

عبارت محاسباتی مورد نظر ما برای محاسبۀ اضافات سطر چیزی شبیه شکل زیر است. آن را به صورت یک فیلد جدید (اضافات سطر) به نمای موجودیت جدید اضافه کرده و آن را ذخیره می‌کنیم (به نسبت کد پیش‌فرض، الیاس spa برای جدول اصلی نما یعنی __SPArticle__ تعریف شده تا تداخل با عبارت داخلی برطرف شود).

به محیط تدبیر باز می‌گردیم، ردیف «کپی ریز اقلام فاکتور فروش» را انتخاب کرده، روی دکمۀ «فیلدها» کلیک می‌کنیم. در پنجرۀ «فیلدهای موجودیت» روی دکمۀ «ایجاد نما» کلیک می‌کنیم.

در پنجرۀ «فهرست نماها» ردیف متناظر نمای موجودیت جدید را فعال کرده، روی «اصلاح» کلیک می‌کنیم تا کد نما نمایش داده شود (بدون استفادۀ مستقیم از نرم‌افزار SQL Server و از طریق این مسیر نیز می‌توانستیم کد نما را تغییر دهیم، اما از آنجا که نرم‌افزار یاد شده امکانات زیادی را جهت اشکالزدایی فرایند اسکریپت‌نویسی فراهم می‌کند روش توصیه شده برای ایجاد یا اصلاح نماهای کاربر؛ استفاده از همان نرم‌افزار است).

پس از تأیید، فیلد جدید «اضافات سطر» ظاهر می‌شود.

نهایتاً در پنجرۀ «فیلدهای موجودیت»، نمای موجودیت را مجدداً انتخاب می‌کنیم تا فیلد «اضافات سطر» به فیلدهای موجودیت نیز اضافه شود.

موجودیت جدید ما آمادۀ استفاده است و می‌توانیم در گزارشهای چاپی از آن استفاده کنیم. در صورتی که تمایل دارید موجودیت جدید تعریف شده در «شرکت»های دیگر مورد استفاده قرار گیرد می‌توانید آن را با استفاده از فرمان کلیک راست «ارسال به فایل» در پنجرۀ «موجویتهای تعریف شده» در فایلی با فرمت XML ذخیره کنید و در شرکت مقصد با استفاده از فرمان «دریافت از فایل» آن را اضافه و استفاده کنید.

به محیط طراحی گزارش‌ساز چاپی می‌رویم و یک گزارش چاپی جدید برای فاکتور فروش می‌سازیم و ستون جدیدی را برای «اضافات سطر» اضافه می‌کنیم، برای مشخص کردن مقدار آن از تابع پارامتریک استفاده می‌کنیم. موجودیت جدید را انتخاب و شرطهای سطح اول و دوم آن را مطابق تصویر زیر تعیین می‌کنیم.

مقدار خروجی تابع را برابر فیلد جدید «اضافات سطر» قرار دهید و از طریق کادر «فرمت» آن را به گونه‌ای قالب‌بندی کنید که در خروجی؛ عدد فارسی نمایش داده شود. با کلیک بر روی دکمۀ پیش‌نمایش، خروجی آن را ببینید.

گزارش چاپی را ذخیره کنید و نتیجۀ نهایی را با فاکتورهای مختلف آزمایش کنید.